package top.hmtools.captcha.filters;

import java.io.IOException;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import top.hmtools.captcha.CaptchaContext;
import top.hmtools.captcha.configuration.CaptchaAutoConfiguration;
import top.hmtools.captcha.configuration.VerifyUris;

@Component
@WebFilter(urlPatterns = {"/*"},filterName = "VerifyCapchaFilter")
public class VerifyCapchaFilter implements Filter{
	
	final Logger logger = LoggerFactory.getLogger(VerifyCapchaFilter.class);
	
	@Autowired
	private CaptchaAutoConfiguration captchaAutoConfiguration;
	
	@Autowired
	private VerifyUris verifyUris;
	
	@Autowired
	private CaptchaContext captchaContext;

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
			throws IOException, ServletException {
		//是否启用验证
		if(!this.captchaAutoConfiguration.getIsEnableVerify()){
			filterChain.doFilter(request, response);
			return;
		}
		
		//获取当前请求URI
		HttpServletRequest httpServletRequest = (HttpServletRequest)request;
		HttpServletResponse httpServletResponse = (HttpServletResponse)response;
		String requestURI = httpServletRequest.getRequestURI();
		if(this.logger.isDebugEnabled()){
			this.logger.debug("当前请求的URI是：{}",requestURI);
		}
		
		//放行方法为 options 的请求
		String requestMethod = httpServletRequest.getMethod();
		if(requestMethod!=null && requestMethod.equalsIgnoreCase("OPTIONS")){
			filterChain.doFilter(httpServletRequest, response);
			return;
		}
		
		//获取当前配置需要拦截并提取验证码验证的URI集合
		if(this.verifyUris == null || this.verifyUris.getUris() == null || this.verifyUris.getUris().isEmpty()){
			filterChain.doFilter(request, response);
			return;
		}
		
		//匹配URI是否需要拦截
		PathMatcher matcher = new AntPathMatcher();
		List<String> uris = this.verifyUris.getUris();
		for(String uri:uris){
			boolean match = matcher.match(uri, requestURI);
			if(!match){
				//不匹配的
				continue;
			}
			
			//匹配的，即要验证验证码是否匹配的
			//提取http请求的验证码参数值
			String verifyParamName = this.captchaAutoConfiguration.getVerifyParamName();
			String captchaValue = httpServletRequest.getParameter(verifyParamName);
			if(this.logger.isDebugEnabled()){
				this.logger.debug("当前配置的验证码http参数名为：{}，当前请求中的验证码参数值为：{}",verifyParamName,captchaValue);
			}
			
			//提取验证码参数值 失败
			if(captchaValue == null || captchaValue.trim().length()<1){
				this.logger.error("http请求{}没有携带验证码！~",requestURI);
				httpServletResponse.setCharacterEncoding("utf-8");
				httpServletResponse.sendError(403, "无验证码");
				return;
			}
			
			//提取验证码参数值 成功
			boolean checkCaptcha = this.captchaContext.checkCaptcha(captchaValue);
			if(checkCaptcha){
				filterChain.doFilter(request, response);
				return;
			}else{
				this.logger.error("http请求{}携带验证码错误！~",requestURI);
				httpServletResponse.setCharacterEncoding("utf-8");
				httpServletResponse.sendError(403, "验证码错误");
				return;
			}
		}
		
		//不匹配的，即不需要被检验验证码的
		if(this.logger.isDebugEnabled()){
			this.logger.debug("不需要验证的URI：{}，给予放行",requestURI);
		}
		filterChain.doFilter(httpServletRequest, httpServletResponse);
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		
	}

}
